/**
 * @file    	main.c
 * @brief   	电子手表的主程序
 * @details 	包含主程序，各模块初始化程序，数据采集与处理部分，屏幕显示等部分
 * 
 */

/***** Includes *****/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mxc_config.h"
#include "nvic_table.h"
#include "i2c.h"
#include "rtc.h"
#include "mxc_delay.h"
#include "tmr.h"
#include "tmr_utils.h"
#include "uart.h"
#include "math.h"

#include "oled.h"
//#include "BMP280.h"
#include "mpu9250.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
/***** Globals *****/
i2c_req_t req;
float pitch, roll, yaw;
short aacx, aacy, aacz;
short gyrox, gyroy, gyroz;
short compass[3];
short temp;
unsigned long step = 0;

#define LED_ALARM 0
#define TIME_OF_DAY_SEC 2
#define SUBSECOND_MSEC_0 125
#define SUBSECOND_MSEC_1 250
#define SECS_PER_MIN 60
#define SECS_PER_HR (60 * SECS_PER_MIN)
#define SECS_PER_DAY (24 * SECS_PER_HR)

#define MSEC_TO_RSSA(x) (0 - ((x * 256) / 1000)) /* Converts a time in milleseconds to the equivalent RSSA register value. */

//////////////////////////MPU9250//////////////////////////////////
#define PI 3.1415926535898
double compassAngle, compassAngle_old;
short compass0[20];
short compass1[20];
u8 x2, y2;
double compass0_avg, compass1_avg;
//初始化9250
void MPU_init()
{
    printf("MPU9250Init\r\n");
    I2C_Init(MXC_I2C0, I2C_FAST_MODE, NULL);
    MPU9250_Init();
    uint8_t err = mpu_dmp_init();
    while (err)
    {
        printf("mpu_init_err:%d\r\n", err);
        while (1)
            ;
    }
    printf("MPU9250Success\r\n");
}

#define COMPASS0 380
#define COMPASS1 930
int MPU_9250Read() //读取9250数据并处理显示
{
    uint8_t i = 0;
    unsigned long time;
    u8 x2, y2;
    temp = MPU_Get_Temperature();
    mpu_get_compass_reg(compass, &time); //获得磁力计原始数据
    dmp_get_pedometer_step_count(&step); //读取步数
    char wendu[9], bushu[10];

    sprintf(wendu, "%.1fC", temp / 100.0);
    sprintf(bushu, "%04ld", step);
    //为磁力计值滤波
    for (i = 0; i < 19; i++)
    {
        compass0[i] = compass0[i + 1];
        compass1[i] = compass1[i + 1];
    }
    compass0[19] = compass[0];
    compass1[19] = compass[1];
    compass0_avg = 0;
    compass1_avg = 0;
    for (i = 0; i < 19; i++)
    {
        compass0_avg += (double)compass0[i] / 20.0;
        compass1_avg += (double)compass1[i] / 20.0;
    }

    //滤波结束

    //处理磁力计值
    if (abs((int)compass1_avg - COMPASS1) > 20)
    {
        compassAngle = atan((compass0_avg - COMPASS0) / (compass1_avg - COMPASS1));
        //printf("channels:%.4f\n",(doubel)(compass[0]-80)/(float)(compass[1]-960));
    }
    else if(abs((int)compass0_avg - COMPASS0) <100)
    {
        //printf("channels:0.0000\n");
        compassAngle = 0;
    }
		else 
    {
        //printf("channels:0.0000\n");
        compassAngle = PI/2;
    }
    compassAngle = compassAngle * 360 / PI;

    if (compassAngle < 0)
    {
        compassAngle = compassAngle + 360;
    }
		//printf("channels:%f,%f,%f\n",compassAngle,compass0_avg,compass1_avg);
    //磁力计处理完成
    //画线
    x2 = 13 + (int)(11 * cos(compassAngle_old / 57.29578)); //清除上次的线
    y2 = 51 - (int)(11 * sin(compassAngle_old / 57.29578));
    if (y2 > 51)
    {
        OLED_DrawLine(13, 51, x2, y2, 0);
    }
    else
    {
        OLED_DrawLine(x2, y2, 13, 51, 0);
    }

    x2 = 13 + (int)(11 * cos(compassAngle / 57.29578)); //画新线
    y2 = 51 - (int)(11 * sin(compassAngle / 57.29578));
    if (y2 > 51)
    {
        OLED_DrawLine(13, 51, x2, y2, 1);
    }
    else
    {
        OLED_DrawLine(x2, y2, 13, 51, 1);
    }
    if (((int)compassAngle - 180) > -45 && ((int)compassAngle - 180) < 45)
    {
        OLED_ShowChar(10, 48, 'E', 8, 1);
    }
    else if (((int)compassAngle - 90) > -45 && ((int)compassAngle - 90) < 45)
    {
        OLED_ShowChar(10, 48, 'N', 8, 1);
    }
    if (((int)compassAngle - 270) > -45 && ((int)compassAngle - 270) < 45)
    {
        OLED_ShowChar(10, 48, 'S', 8, 1);
    }
    if (((int)compassAngle - 0) > -45 && ((int)compassAngle - 0) < 45)
    {
        OLED_ShowChar(10, 48, 'W', 8, 1);
    }
    compassAngle_old = compassAngle; //保存本次角度，用来下次清除
    //画线完成

    //printf("channels:%.4f,%.4f,%.4f\n", compassAngle, compass0_avg, compass1_avg);
    OLED_ShowString(30, 43, wendu, 16, 1);
    OLED_ShowString(80, 43, bushu, 16, 1);
    return 0;
}
////////////////////////////////RTC//////////////////////////////////////////
#define START_HR 13
#define START_MIN 30
#define START_SEC 00
#define START_YEAR 2021
#define START_MOON 3
#define START_DAY 6

//闰年判断
uint8_t leap(int year)
{
    int four, hundred, fourhundred;
    four = year % 4;
    hundred = year % 100;
    fourhundred = year % 400;
    if (four == 0 && hundred == 0 && fourhundred == 0)
        return 1;
    else if (four == 0 && hundred != 0 && fourhundred != 0)
        return 1;
    else
        return 0;
}
//获取rtc时间并处理显示
//RTC初始化，hr=小时，min=分钟，sec=秒
void RTC_init(uint8_t day, uint8_t hr, uint8_t min, uint32_t sec)
{
    sys_cfg_rtc_t sys_cfg;
    NVIC_EnableIRQ(RTC_IRQn);
    RTC_DisableRTCE(MXC_RTC);

    sys_cfg.tmr = MXC_TMR2;
    if (RTC_Init(MXC_RTC, day * SECS_PER_DAY + hr * SECS_PER_HR + min * SECS_PER_MIN + sec, 0, &sys_cfg) != E_NO_ERROR)
    {
        printf("Failed RTC_Setup().\n");
        while (1)
            ;
    }
    if (RTC_EnableRTCE(MXC_RTC) != E_NO_ERROR)
    {
        printf("Failed RTC_EnableRTCE().\n");
        while (1)
            ;
    }
}
//屏幕显示时间
uint8_t day, hr, min;
int moon, year;
uint32_t sec;
void printTime(void)
{
    double subsec;
    subsec = RTC_GetSubSecond() / 256.0;
    sec = RTC_GetSecond();
    day = sec / SECS_PER_DAY;
    sec -= day * SECS_PER_DAY;
    hr = sec / SECS_PER_HR;
    sec -= hr * SECS_PER_HR;
    min = sec / SECS_PER_MIN;
    sec -= min * SECS_PER_MIN;
    subsec += sec;

    if ((moon == 1) || (moon == 3) || (moon == 5) || (moon == 7) || (moon == 8) || (moon == 10) || (moon == 12))
    {
        if (day == 32)
        {
            day = 1;
            moon++;
            RTC_init(day, hr, min, sec);
        }
    }
    else if (moon == 2 && (leap(year) == 1))
    {
        if (day == 30)
        {
            day = 1;
            moon++;
            RTC_init(day, hr, min, sec);
        }
    }
    else if (moon == 2 && (leap(year) == 0))
    {
        if (day == 29)
        {
            day = 1;
            moon++;
            RTC_init(day, hr, min, sec);
        }
    }
    else
    {
        if (day == 31)
        {
            day = 1;
            moon++;
            RTC_init(day, hr, min, sec);
        }
    }
    if (moon == 13)
    {
        moon = 1;
        year++;
    }

    char time[8];
    char wannianli[10];
    sprintf(time, "%02d:%02d:%02d", hr, min, sec);
    sprintf(wannianli, "%d-%02d-%02d", year, moon, day);
    OLED_ShowString(10, 0, time, 24, 1);
    OLED_ShowString(18, 24, wannianli, 16, 1);
}

//////////////////////////////TMR////////////////////////////////////////
//TMR1中断-50Hz
#define INTERVAL_TIME_CONT 20
void ContinuousTimer_Handler(void)
{
    /* Clear interrupt */
    TMR_IntClear(MXC_TMR1);
    MPU_9250Read();
}
//TMR1初始化为50Hz触发中断
void tmr1_init()
{
    tmr_cfg_t tmr;
    NVIC_SetVector(TMR1_IRQn, ContinuousTimer_Handler);
    NVIC_EnableIRQ(TMR1_IRQn);
    uint32_t period_ticks = PeripheralClock / 4000 * INTERVAL_TIME_CONT;
    TMR_Disable(MXC_TMR1);
    TMR_Init(MXC_TMR1, TMR_PRES_4, 0);
    tmr.mode = TMR_MODE_CONTINUOUS;
    tmr.cmp_cnt = period_ticks;
    tmr.pol = 0;
    TMR_Config(MXC_TMR1, &tmr);

    TMR_Enable(MXC_TMR1);
}

/////////////////////////OLED////////////////////////////////
//初始化OLED
void oled_init()
{
    printf("OLED_INIT\r\n");
    OLED_Init();
    OLED_ColorTurn(0);
    OLED_DisplayTurn(0);
    OLED_DrawCircle(13, 51, 12);

    printf("OLED_Success\r\n");
}
//////////////////////////UART//////////////////////////
volatile int read_flag;
uart_req_t read_req;
int error = 0;
uint8_t time[19];
void UART1_IRQHandler(void)
{
    UART_Handler(MXC_UART1);
}
void read_cb(uart_req_t *req, int error)
{
    read_flag = error;
}
void UART_SETUP()
{
    NVIC_SetVector(UART1_IRQn, UART1_IRQHandler);
    NVIC_ClearPendingIRQ(MXC_UART_GET_IRQ(1));
    NVIC_DisableIRQ(MXC_UART_GET_IRQ(1));
    NVIC_SetPriority(MXC_UART_GET_IRQ(1), 1);
    NVIC_EnableIRQ(MXC_UART_GET_IRQ(1));

    uart_cfg_t cfg;
    cfg.parity = UART_PARITY_DISABLE;
    cfg.size = UART_DATA_SIZE_8_BITS;
    cfg.stop = UART_STOP_1;
    cfg.flow = UART_FLOW_CTRL_EN;
    cfg.pol = UART_FLOW_POL_EN;
    cfg.baud = 115200;
    const sys_cfg_uart_t sys_uart_cfg = {
        MAP_A,
        UART_FLOW_DISABLE,
    };
    error = UART_Init(MXC_UART_GET_UART(1), &cfg, &sys_uart_cfg);
    if (error != E_NO_ERROR)
    {
        printf("Error initializing UART %d\n", error);
        while (1)
            ;
    }

    read_req.data = time;
    read_req.len = 19;
    read_req.callback = read_cb;
    read_flag = 1;
    error = UART_ReadAsync(MXC_UART_GET_UART(1), &read_req);
    if (error != E_NO_ERROR)
    {
        printf("Error starting async read %d\n", error);
        while (1)
            ;
    }
}
// *****************************************************************************

int main(void)
{
    year = START_YEAR;
    moon = START_MOON;
    day = START_DAY;
    hr = START_HR;
    min = START_MIN;
    sec = START_SEC;
    RTC_init(day, hr, min, sec);
    MPU_init();
    oled_init();
    tmr1_init();
    UART_SETUP();
    while (1)
    {
        if (read_flag == 0)
        {
            year = (time[0] - '0') * 1000 + (time[1] - '0') * 100 + (time[2] - '0') * 10 + (time[3] - '0');
            moon = (time[5] - '0') * 10 + (time[6] - '0');
            day = (time[8] - '0') * 10 + (time[9] - '0');
            hr = (time[11] - '0') * 10 + (time[12] - '0');
            min = (time[14] - '0') * 10 + (time[15] - '0');
            sec = (time[17] - '0') * 10 + (time[18] - '0');
            error = UART_ReadAsync(MXC_UART_GET_UART(1), &read_req);
            RTC_init(day, hr, min, sec);

            read_flag = 1;
            printf("Clock Correct success!\r\n");
        }
        printTime();
        OLED_Refresh();
        delay_ms(200);
    }
}
